import { Command } from 'commander';
import chalk from 'chalk';
import WebSocket from 'ws';
import readline from 'readline';
import { fetchUserOpsToken } from '../utils/OpsUser.js';
import { opsRequest } from '../utils/OpsClient.js';
import { createLogger } from '../utils/Logger.js';
import {getGlobalOpsFile, getProjectOpsFile, initGlobalProjectOpsFile} from "../utils/OpsFile.js";
import process from "process";
import {StrUtil} from "../utils/StrUtil.js";
import {DateUtil} from "../utils/DateUtil.js";

const ANSI_COLOR_REGEX = /\x1B\[[0-9;]*m/g;
const DEFAULT_LOG_PREFIX = 'buzz_service';


/**
 * OC 命令处理器 - Pod 控制台连接工具
 */
class OcCommandHandler {
    constructor() {
        this.program = new Command();
        this.rl = null;
        this.logger = createLogger('OC');
        this.projectOpsFile = null;
        this.globalopsFile = getGlobalOpsFile();
        this.projectCacheFile = initGlobalProjectOpsFile();
        this.commandMode = false; // 标记是否在命令模式
        this.inputBuffer = ''; // 输入缓冲区
        this.lastCtrlCAt = 0; // 最近一次 Ctrl+C 的时间戳
        this.ctrlCExitIntervalMs = 1000; // 双击 Ctrl+C 退出的时间窗口
        this.ctrlCResetTimer = null; // 重置 Ctrl+C 状态的定时器
        this.consoleSocket = null; // 当前的 WebSocket 连接实例
        this.currentCommandBuffer = ''; // 普通模式下的命令缓冲
        this.lastCharWasCR = false; // 是否刚处理过回车
        this.autoTailInProgress = false; // 是否在自动 tail 过程中
        this.outputInterceptor = null; // WebSocket 输出拦截器
        this.setupCommands();
    }

    /**
     * 设置命令和参数
     */
    setupCommands() {
        this.program
            .name('oc')
            .description('OC 工具 - 连接到 Pod 控制台')
            .version('1.0.0');

        // 主命令 - 连接控制台
        this.program
            .argument('[pod_name]', 'Pod 名称')
            .option('-u', '连接到 UAT 环境', false)
            .option('-f', '连接到 Feature 环境', false)
            .option('-t, --ft', '连接到 Feature Tag 环境', false)
            .option('--tail', '连接后自动 tail 当前服务最新日志', false)
            .option('--t', '连接后自动 tail 当前服务最新日志 (兼容输入)', false)
            .option('-b', '连接到 Beta 环境', false)
            .option('-p', '连接到 Prod 环境', false)
            .option('-v, --verbose', '详细输出', false)
            .action((podName, options) => {
                this.handleConnectCommand(podName, options);
            });

        // 子命令 - 列出可用环境
        this.program
            .command('list')
            .alias('ls')
            .argument('[pod_name]', 'Pod 名称')
            .description('列出指定 Pod 的所有可用环境')
            .action((podName) => {
                this.handleListCommand(podName);
            });

        this.program.addHelpText('after', () => `
示例：
  oc buzz_service -u             连接 UAT 环境（默认值）
  oc buzz_service -f --tail      连接 Feature/FT 环境并自动 tail 最新 ${DEFAULT_LOG_PREFIX} 日志
  oc list buzz_service           查看指定应用的可用环境列表

常用参数：
  -u/-f/-t/--ft/-b/-p            选择环境，仅能二选一（默认 UAT）
  --tail/--t                     连接后自动 tail ${DEFAULT_LOG_PREFIX} 日志文件
  -v, --verbose                  打开调试输出

提示：
  连接成功后按 Ctrl+\\ 进入命令模式，支持 quit/clear/help/ctrl-c；连续按两次 Ctrl+C 断开连接。
`);
    }

    /**
     * 处理连接命令 (主要逻辑) - 增强版本
     */
    async handleConnectCommand(podName, options) {
        const { verbose } = options;
        const autoTailRequested = Boolean(options.tail || options.t);
        const trimmedPodName = (podName || '').trim();
        const autoTailServiceName = autoTailRequested && trimmedPodName ? trimmedPodName : null;
        this.logger.log(`指令：${JSON.stringify(options)}`)
        try {
            this.logger.step(1, '开始连接 Pod 控制台');
            this.logger.log(`Pod 名称: ${podName || '未指定'}`);

            if (autoTailRequested && !podName) {
                this.logger.warn('检测到 --t/--tail 标记但未提供 Pod 名称，已忽略自动 tail');
            }

            // 解析环境参数
            this.logger.step(2, '解析环境参数');
            const profile = this.parseEnvironmentFromOptions(options);
            this.logger.log(`Profile: ${profile}`);

            const profileEnv = this.validateAndMapProfile(profile);
            this.logger.log(`profileEnv: ${profileEnv}`);

            // 加载配置
            this.logger.step(3, '加载配置文件');
            const config = await this.loadConfiguration(podName);

            // 获取认证 token
            this.logger.step(4, '获取认证 Token');
            const token = await this.getAuthToken(config.opsUser, verbose);

            // 获取应用数据和环境列表
            this.logger.step(5, '查询可用环境');
            let environments = await this.getAvailableEnvironments(
                config.flowId,config.opsName, profile, token,profileEnv, verbose
            );

            // 选择环境 - 支持刷新和重试
            this.logger.step(6, '选择目标环境');
            const selectedEnv = await this.selectEnvironment(
                environments,
                config.flowId,
                config.opsName,
                config,
                profile,
                profileEnv,
                token
            );

            // 连接 WebSocket 控制台
            this.logger.step(7, '建立控制台连接');
            await this.connectToConsole(selectedEnv, token, {
                verbose,
                isBase: config.isBase,
                profile,
                autoTailEnabled: autoTailRequested,
                autoTailServiceName
            });

        } catch (error) {
            this.logger.error('连接失败:', error.message);
            if (this.rl) {
                this.rl.close();
            }
            process.exit(1);
        }
    }

    /**
     * 处理列表命令
     */
    async handleListCommand(podName) {
        try {
            console.log(chalk.blue('📋 查询可用环境...'));

            const config = await this.loadConfiguration(podName);
            const token = await this.getAuthToken(config.opsUser);

            // 获取所有环境的信息
            const appData = await opsRequest(
                new URL('https://vops.hszq8.com/app/api/v1/app/' + config.opsName),
                token
            );

            const keys = [
                ...Object.keys(appData.server_nodes || {}),
                ...Object.keys(appData.server_nodes_prod || {})
            ];

            console.log(chalk.green(`\n📦 ${config.opsName} 的所有环境:`));
            for (const key of keys) {
                console.log(`  • ${key}`);
            }

        } catch (error) {
            console.error(chalk.red('❌ 获取环境列表失败:'), error.message);
            process.exit(1);
        }
    }

    /**
     * 从选项中解析环境参数
     */
    parseEnvironmentFromOptions(options) {
        const envFlags = ['u', 'f', 'ft', 'b', 'p'];
        const selectedEnvs = envFlags.filter(flag => options[flag]);

        if (selectedEnvs.length === 0) {
            return 'u'; // 默认使用 UAT 环境
        }

        if (selectedEnvs.length > 1) {
            throw new Error(`只能选择一个环境，当前选择了: ${selectedEnvs.join(', ')}`);
        }

        return selectedEnvs[0];
    }

    /**
     * 验证和映射 profile 参数
     */
    validateAndMapProfile(profile) {
        const profileMap = {
            f: 'feature',
            ft: 'feature',
            u: 'uat',
            b: 'beta',
            p: 'prod',
        };

        if (!profileMap[profile]) {
            throw new Error(`非法参数 profile: ${profile}，有效值: ${Object.keys(profileMap).join(', ')}`);
        }

        return profileMap[profile];
    }

    /**
     * 加载配置文件
     */
    async loadConfiguration(podName) {
        const trimmedPodName = (podName || '').trim();
        const opsUser = await this.globalopsFile.read(('ops_user'));
        let flowId = null;
        let isBase = false;
        let opsName = null;

        if (!this.projectOpsFile) {
            try {
                this.projectOpsFile = getProjectOpsFile();
                this.logger.info(`已加载项目级 ops.conf: ${this.projectOpsFile.opsFilePath}`);
            } catch (error) {
                this.logger.warn(`未检测到项目级 ops.conf，尝试使用全局缓存或输入值：${error.message}`);
            }
        }

        if (this.projectOpsFile) {
            const flowJzPath = await this.projectOpsFile.read((`flow_jz.${podName}.path`));
            flowId = await this.projectOpsFile.read((`flow.id`));
            isBase = StrUtil.notNull(flowJzPath);
            opsName = await this.projectOpsFile.read((`flow.${podName}.opsName`));
            // 基座配置
            if (!opsName && isBase) {
                opsName = await this.projectOpsFile.read((`flow_jz.${flowJzPath}.opsName`));
            }
            // 基座应用
            if (!opsName) {
                opsName = await this.projectOpsFile.read((`flow_jz_plugin.${podName}.opsName`));
            }
        }

        if (!opsName && trimmedPodName) {
            const cachedAppName = this.projectCacheFile.read((`app.${trimmedPodName}`));
            if (cachedAppName) {
                opsName = cachedAppName;
                this.logger.info(`使用全局缓存 app.${trimmedPodName} => ${opsName}`);
            }
        }

        if (!opsName && trimmedPodName) {
            const cachedBaseName = this.projectCacheFile.read((`jz.${trimmedPodName}`));
            if (cachedBaseName) {
                opsName = cachedBaseName;
                this.logger.info(`使用全局缓存 jz.${trimmedPodName} => ${opsName}`);
            }
        }

        if (!opsName && trimmedPodName) {
            opsName = trimmedPodName;
            this.logger.info(`未找到缓存或项目配置，直接使用输入值作为 opsName: ${opsName}`);
        }

        if (!opsName) {
            throw new Error(`ops.properties 文件中缺少 opsName 配置或值为空 无法连接`);
        }

        return {
            opsUser,
            opsName,
            flowId,
            isBase
        };
    }

    /**
     * 获取认证 token
     */
    async getAuthToken(opsUser, verbose = false) {
        this.logger.debug(`获取用户 ${opsUser} 的认证 token...`);

        const token = await fetchUserOpsToken(opsUser);

        this.logger.debug('Token 获取成功');
        return token;
    }

    /**
     * 获取可用环境列表 - 增强版本，添加重试和错误处理
     */
    async getAvailableEnvironments(flowId,opsName, profile, token,profileEnv, verbose = false, isRefresh = false) {
        if (isRefresh) {
            this.logger.log(`刷新查询 ${opsName} 在 ${profileEnv} 环境的实例...`);
        } else {
            this.logger.log(`查询 ${opsName} 在 ${profileEnv} 环境的实例...`);
        }

        try {
            const appData = await opsRequest(
                new URL('https://vops.hszq8.com/app/api/v1/app/' + opsName),
                token
            );

            const keys = [
                ...Object.keys(appData.server_nodes || {}),
                ...Object.keys(appData.server_nodes_prod || {})
            ];

            const environments = [];

            for (const key of keys) {
                if (key.includes(profileEnv)) {
                    this.logger.debug(`找到匹配的环境键: ${key}`);

                    try {
                        const envData = await opsRequest(
                            new URL(`https://vops.hszq8.com/app/api/v1/apps/podv2/${opsName}/${key}`),
                            token
                        );

                        if (this.isEmptyObject(envData)) {
                            this.logger.debug(`环境 ${key} 数据为空，跳过`);
                            continue;
                        }

                        // 处理环境数据
                        Object.keys(envData).forEach(envKey => {
                            const envValueData = envData[envKey];
                            const podEnvName = envValueData.metadata.name;
                            // 创建时间
                            const creationTimestamp = envValueData.metadata.creation_timestamp;
                            const image = envValueData.status.app_status.image;
                            // 如果＞0就
                            const restart = envValueData.status.app_status.restart;
                            // ready!=total 就是启动中
                            const ready = envValueData.status.app_status.ready;
                            const total = envValueData.status.app_status.total;
                            let restartValue = ``;
                            if (restart === 0) {
                                if (ready !== total) {
                                    restartValue = '启动中';
                                }
                            } else if (restart > 0) {
                                restartValue = `重启${restart}次`;
                            }
                            // Running
                            const phase = envValueData.status.phase;

                            // 提取 Pod 标识符
                            const podEnvNameLast = podEnvName.substring(podEnvName.lastIndexOf('-') + 1);
                            const imageKey = image.substring(image.lastIndexOf('/') + 1);

                            this.logger.debug(`处理 Pod: ${podEnvName}, Image: ${imageKey}`);

                            let envDesc = `【${podEnvNameLast}】`;

                            // 根据环境类型添加描述
                            if (['f', 'u', 'b', 'p'].includes(profile)) {
                                // 稳定环境
                                if (!envValueData?.attached?.version) {
                                    envDesc += `稳定环境 (${profileEnv})[${phase}]:${creationTimestamp} ${restartValue}`;
                                    environments.push({
                                        podKey: envKey,
                                        envDesc: envDesc,
                                        imageKey: imageKey
                                    });
                                }
                            } else {
                                // tag 环境
                                if (envValueData?.attached?.version) {
                                    const rid = envValueData.attached.version.rid;
                                    if (!flowId || rid === flowId) {
                                        envDesc += `tag环境 (${envValueData.attached.version.item_name}) [${envValueData.metadata.namespace}][${phase}]:${creationTimestamp} ${restartValue}`;
                                        environments.push({
                                            podKey: envKey,
                                            envDesc: envDesc,
                                            imageKey: imageKey
                                        });
                                    }
                                }
                            }
                        });
                        break;
                    } catch (envError) {
                        this.logger.warn(`获取环境 ${key} 详细信息失败: ${envError.message}`);
                        continue; // 跳过这个环境，继续处理其他环境
                    }
                }
            }

            if (environments.length === 0) {
                if (isRefresh) {
                    throw new Error(`刷新后仍未找到匹配的 "${profileEnv}" 环境`);
                } else {
                    throw new Error(`未找到匹配的 "${profileEnv}" 环境`);
                }
            }

            if (isRefresh) {
                this.logger.debug(`刷新完成，找到 ${environments.length} 个可用环境`);
            } else {
                this.logger.debug(`找到 ${environments.length} 个可用环境`);
            }

            return environments;

        } catch (error) {
            if (isRefresh) {
                throw new Error(`刷新环境列表失败: ${error.message}`);
            } else {
                throw error;
            }
        }
    }

    /**
     * 选择环境 - 增强版本，支持刷新和重试 + 自动刷新
     */
    async selectEnvironment(environments, opsName,flowId, config, profile,profileEnv, token) {
        let currentEnvironments = environments;

        while (true) {
            // 如果只有一个环境，直接选择
            if (currentEnvironments.length === 1) {
                return currentEnvironments[0];
            }

            // 多个环境时让用户选择
            this.logger.info(`请选择环境 (${opsName}):`);
            currentEnvironments.forEach((item, index) => {
                console.log(`  ${chalk.yellow(index + 1)}. ${item.envDesc}`);
            });
            console.log(`  ${chalk.cyan('r')}. 刷新环境列表`);
            console.log(`  ${chalk.red('q')}. 退出`);

            this.rl = readline.createInterface({
                input: process.stdin,
                output: process.stdout,
            });

            let timeoutId;
            const timeoutPromise = new Promise(resolve => {
                timeoutId = setTimeout(() => resolve('__AUTO_REFRESH__'), 5000);
            });

            // 竞速：用户输入 vs 超时
            const answer = await Promise.race([
                this.askQuestion('请输入数字选择对应环境 (或输入 r 刷新, q 退出): '),
                timeoutPromise
            ]);

            clearTimeout(timeoutId);
            // 处理用户输入 / 自动刷新标记
            let trimmedAnswer;
            if (answer === '__AUTO_REFRESH__') {
                trimmedAnswer = '__AUTO_REFRESH__';
            } else {
                trimmedAnswer = answer && answer.trim ? answer.trim().toLowerCase() : '';
            }

            // 自动刷新
            if (trimmedAnswer === '__AUTO_REFRESH__') {
                this.rl.close();
                console.log(chalk.blue('⏰ 5 秒无输入，自动刷新环境列表...'));
                try {
                    currentEnvironments = await this.getAvailableEnvironments(
                        flowId,config.opsName,profile , token,profileEnv, false, true
                    );
                    this.logger.success(`刷新完成，找到 ${currentEnvironments.length} 个环境`);
                    continue; // 重新开始选择循环
                } catch (error) {
                    this.logger.error('刷新环境列表失败:', error.message);
                    console.log(chalk.yellow('使用之前的环境列表继续...'));
                    continue;
                }
            }

            // 处理特殊命令
            if (trimmedAnswer === 'r' || trimmedAnswer === 'refresh') {
                this.rl.close();
                console.log(chalk.blue('🔄 正在刷新环境列表...'));

                try {
                    currentEnvironments = await this.getAvailableEnvironments(
                        flowId,config.opsName, profile, token, profileEnv,false, true
                    );
                    this.logger.success(`刷新完成，找到 ${currentEnvironments.length} 个环境`);
                    continue;
                } catch (error) {
                    this.logger.error('刷新环境列表失败:', error.message);
                    console.log(chalk.yellow('使用之前的环境列表继续...'));
                    continue;
                }
            }

            if (trimmedAnswer === 'q' || trimmedAnswer === 'quit' || trimmedAnswer === 'exit') {
                this.rl.close();
                throw new Error('用户主动退出');
            }

            // 处理数字选择
            if (trimmedAnswer === '') {
                this.rl.close();
                console.log(chalk.yellow('⚠️  未输入任何内容，请重新选择'));
                continue;
            }

            const choice = parseInt(trimmedAnswer, 10);

            if (isNaN(choice) || choice <= 0 || choice > currentEnvironments.length) {
                this.rl.close();
                console.log(chalk.red(`❌ 输入无效: "${answer}"`));
                console.log(chalk.yellow('💡 请输入 1-' + currentEnvironments.length + ' 之间的数字，或输入 "r" 刷新环境列表'));
                continue;
            }

            // 有效选择
            this.rl.close();
            const selected = currentEnvironments[choice - 1];
            this.logger.info(`已选择环境: ${selected.envDesc}`);
            return selected;
        }
    }


    /**
     * 连接到 WebSocket 控制台
     */
    async connectToConsole(selectedEnv, token, options = {}) {
        const {
            verbose = false,
            isBase = false,
            profile = 'u',
            autoTailEnabled = false,
            autoTailServiceName = null
        } = options;
        this.logger.info(`正在连接控制台: ${selectedEnv.envDesc}`);
        this.logger.debug(`Image: ${selectedEnv.imageKey}`);
        this.logger.debug(`Pod Key: ${selectedEnv.podKey}`);
        const logDirectory = profile === 'p'
            ? '/logs'
            : (isBase ? '/data0/opt/koupleless/logs' : '/data0/opt/tomcat_default/logs');
        if (verbose) {
            this.logger.debug(`初始日志目录: ${logDirectory}`);
        }

        const wsUrl = `wss://vops.hszq8.com/app/api/v1/console/hs_bss_admin_server/pod_console?key=${selectedEnv.podKey}&token=${token}&version=v2`;

        const ws = new WebSocket(wsUrl, {
            headers: {
                Origin: 'https://vops.hszq8.com',
                'Cache-Control': 'no-cache',
                'Pragma': 'no-cache',
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'
            }
        });

        return new Promise((resolve, reject) => {
            this.consoleSocket = ws;
            ws.on('open', () => {
                this.logger.success(`已连接到远程控制台,自动进入 ${logDirectory} 目录`);
                console.log(chalk.gray('💡 使用提示:'));
                console.log(chalk.gray('   • 连续按两次 Ctrl+C 可直接断开连接'));
                console.log(chalk.gray('   • 按 Ctrl+\\ 进入命令模式'));
                console.log(chalk.gray('   • 在命令模式下输入 "quit" or "q" 断开连接'));
                console.log(chalk.gray('   • 在命令模式下输入 "help" 查看更多帮助'));
                console.log(chalk.gray('   • 按 Esc 退出命令模式\n'));

                this.setupConsoleInteraction(ws);
                // 🚀 直接切换到日志目录
                ws.send(`cd ${logDirectory}\n`);

                if (autoTailEnabled) {
                    if (autoTailServiceName && autoTailServiceName !== DEFAULT_LOG_PREFIX) {
                        this.logger.info(`日志文件统一为 ${DEFAULT_LOG_PREFIX}，已忽略服务名 ${autoTailServiceName}`);
                    }
                    this.logger.info(`检测到 --t/--tail，自动 tail ${DEFAULT_LOG_PREFIX} 最新日志`);
                    setTimeout(() => {
                        this.startAutoTailFlow(autoTailServiceName, ws);
                    }, 300);
                }

                resolve();
            });

            ws.on('message', (data) => {
                const text = data.toString();
                if (this.outputInterceptor) {
                    this.consumeInterceptedOutput(text);
                    return;
                }
                this.forwardConsoleOutput(text);
            });

            ws.on('close', () => {
                if (this.outputInterceptor && typeof this.outputInterceptor.reject === 'function') {
                    this.outputInterceptor.reject(new Error('连接已关闭'));
                }
                this.outputInterceptor = null;
                this.consoleSocket = null;
                this.logger.warn('连接已关闭');
                this.restoreTerminal();
                process.exit(0);
            });

            ws.on('error', (err) => {
                if (this.outputInterceptor && typeof this.outputInterceptor.reject === 'function') {
                    this.outputInterceptor.reject(err);
                }
                this.outputInterceptor = null;
                this.consoleSocket = null;
                this.logger.error('WebSocket 错误:', err.message);
                this.restoreTerminal();
                reject(err);
            });
        });
    }

    /**
     * 显示命令模式帮助
     */
    showCommandHelp() {
        console.log(chalk.cyan('\n📖 命令模式帮助:'));
        console.log(chalk.white('  quit    - 断开控制台连接并退出'));
        console.log(chalk.white('  clear   - 清屏'));
        console.log(chalk.white('  help    - 显示此帮助信息'));
        console.log(chalk.white('  ctrl-c  - 发送 Ctrl+C 到远程终端 (用于中断 tail 等命令)'));
        console.log(chalk.gray('  按 Esc 键退出命令模式\n'));
    }

    /**
     * 处理命令模式输入
     */
    handleCommandInput(ws, input) {
        const command = input.trim().toLowerCase();

        switch (command) {
            case 'quit':
            case 'q':
            case 'exit':
                this.logger.warn('用户主动断开连接');
                this.restoreTerminal();
                ws.close();
                process.exit(0);
                break;

            case 'clear':
            case 'cls':
                console.clear();
                break;

            case 'help':
            case '?':
                this.showCommandHelp();
                break;

            case 'ctrl-c':
                // 发送 Ctrl+C 到远程终端
                if (ws.readyState === WebSocket.OPEN) {
                    ws.send('\u0003');
                    console.log(chalk.yellow('✓ 已发送 Ctrl+C 到远程终端'));
                }
                break;

            case '':
                // 空命令，不做任何操作
                break;

            default:
                console.log(chalk.red(`❌ 未知命令: ${command}`));
                console.log(chalk.gray('输入 "help" 查看可用命令'));
        }
    }

    /**
     * 设置控制台交互
     */
    setupConsoleInteraction(ws) {
        // 设置原始模式，直接传输按键
        process.stdin.setRawMode(true);
        process.stdin.resume();
        process.stdin.setEncoding('utf8');

        // 监听所有键盘输入
        process.stdin.on('data', (chunk) => {
            // Ctrl+\ (ASCII 28) - 进入命令模式
            if (chunk === '\u001c') {
                this.commandMode = true;
                this.inputBuffer = '';
                console.log(chalk.cyan('\n🔧 命令模式 (输入 "help" 查看帮助, Esc 退出): '));
                process.stdout.write('> ');
                return;
            }

            // Ctrl+C - 支持双击退出
            if (chunk === '\u0003') {
                if (ws.readyState === WebSocket.OPEN) {
                    ws.send(chunk);
                }
                const now = Date.now();
                if (this.lastCtrlCAt && (now - this.lastCtrlCAt) <= this.ctrlCExitIntervalMs) {
                    if (this.ctrlCResetTimer) {
                        clearTimeout(this.ctrlCResetTimer);
                        this.ctrlCResetTimer = null;
                    }
                    this.commandMode = false;
                    this.inputBuffer = '';
                    this.logger.warn('用户主动断开连接');
                    this.restoreTerminal();
                    ws.close();
                    process.exit(0);
                }
                this.lastCtrlCAt = now;
                if (this.ctrlCResetTimer) {
                    clearTimeout(this.ctrlCResetTimer);
                }
                this.ctrlCResetTimer = setTimeout(() => {
                    this.lastCtrlCAt = 0;
                    this.ctrlCResetTimer = null;
                }, this.ctrlCExitIntervalMs);
                console.log(chalk.gray('\n已发送 Ctrl+C 到远端，1 秒内再次按 Ctrl+C 可断开连接'));
                return;
            }

            if (this.commandMode) {
                // 在命令模式下处理输入
                if (chunk === '\u001b') {
                    // Esc 键 - 退出命令模式
                    this.commandMode = false;
                    this.inputBuffer = '';
                    console.log(chalk.gray('\n退出命令模式\n'));
                    return;
                } else if (chunk === '\r') {
                    // 回车键 - 执行命令
                    console.log(); // 换行
                    this.handleCommandInput(ws, this.inputBuffer);
                    this.commandMode = false;
                    this.inputBuffer = '';
                    return;
                } else if (chunk === '\u007f') {
                    // 退格键
                    if (this.inputBuffer.length > 0) {
                        this.inputBuffer = this.inputBuffer.slice(0, -1);
                        process.stdout.write('\b \b');
                    }
                    return;
                } else if (chunk >= ' ' && chunk <= '~') {
                    // 可打印字符
                    this.inputBuffer += chunk;
                    process.stdout.write(chunk);
                    return;
                }
            } else {
                this.handleNormalInput(ws, chunk);
            }
        });
    }

    handleNormalInput(ws, chunk) {
        if (typeof chunk !== 'string' || !chunk.length) {
            return;
        }
        for (const ch of chunk) {
            const consumed = this.processBufferedCommand(ws, ch);
            if (!consumed && ws.readyState === WebSocket.OPEN) {
                ws.send(ch);
            }
        }
    }

    processBufferedCommand(ws, ch) {
        if (ch === '\r') {
            this.lastCharWasCR = true;
            return this.submitBufferedCommand(ws);
        }
        if (ch === '\n') {
            if (this.lastCharWasCR) {
                this.lastCharWasCR = false;
                return true; // 忽略回车后的换行
            }
            return this.submitBufferedCommand(ws);
        }
        this.lastCharWasCR = false;
        if (ch === '\u007f' || ch === '\b') {
            if (this.currentCommandBuffer.length > 0) {
                this.currentCommandBuffer = this.currentCommandBuffer.slice(0, -1);
            }
            return false;
        }
        if (ch >= ' ' && ch <= '~') {
            this.currentCommandBuffer += ch;
        }
        return false;
    }

    submitBufferedCommand(ws) {
        const buffered = this.currentCommandBuffer.trim();
        this.currentCommandBuffer = '';
        if (!buffered) {
            return false;
        }
        const serviceName = this.extractAutoTailTarget(buffered);
        if (serviceName) {
            this.clearRemoteCurrentLine(ws);
            this.startAutoTailFlow(serviceName, ws);
            return true;
        }
        return false;
    }

    extractAutoTailTarget(commandStr) {
        if (!commandStr) {
            return null;
        }
        const match = commandStr.match(/^nb\s+-([a-z]+)\s+([\w.-]+)\s+--(t|tail)\s*$/i);
        if (!match) {
            return null;
        }
        const envFlag = match[1].toLowerCase();
        const allowedEnvs = ['f', 't', 'ft', 'p', 'u', 'b'];
        if (!allowedEnvs.includes(envFlag)) {
            return null;
        }
        return match[2];
    }

    clearRemoteCurrentLine(ws) {
        if (ws.readyState !== WebSocket.OPEN) {
            return;
        }
        ws.send('\u0015'); // Ctrl+U 清空当前行
        ws.send('\r');
    }

    startAutoTailFlow(serviceName, ws) {
        if (this.autoTailInProgress) {
            this.logger.warn('自动 tail 正在执行，请稍候再试');
            return;
        }
        if (!ws || ws.readyState !== WebSocket.OPEN) {
            this.logger.warn('连接未就绪，无法自动 tail');
            return;
        }
        this.autoTailInProgress = true;
        this.performAutoTail(serviceName, ws)
            .catch((error) => {
                this.logger.error(`自动 tail 失败: ${error.message}`);
            })
            .finally(() => {
                this.autoTailInProgress = false;
            });
    }

    async performAutoTail(serviceName, ws) {
        const marker = `__NB_AUTO__${Date.now()}_${Math.random().toString(16).slice(2)}`;
        const capturePromise = this.captureConsoleOutput(marker);
        ws.send(`ll; echo ${marker}\n`);
        const listing = await capturePromise;
        const selection = this.selectLatestBuzzLog(listing);
        if (!selection) {
            this.logger.warn(`未找到 ${DEFAULT_LOG_PREFIX} 日志文件`);
            return;
        }
        this.logger.info(`已定位日志：${selection.file}`);
        ws.send(`tail -200f ${selection.file}\n`);
    }

    captureConsoleOutput(marker, timeoutMs = 5000) {
        return new Promise((resolve, reject) => {
            if (this.outputInterceptor) {
                reject(new Error('已有输出解析任务进行中，请稍后再试'));
                return;
            }
            const timer = setTimeout(() => {
                if (this.outputInterceptor && this.outputInterceptor.marker === marker) {
                    this.outputInterceptor = null;
                }
                reject(new Error('解析日志目录超时'));
            }, timeoutMs);
            this.outputInterceptor = {
                marker,
                buffer: '',
                timer,
                resolve: (data) => {
                    clearTimeout(timer);
                    resolve(data);
                },
                reject: (err) => {
                    clearTimeout(timer);
                    reject(err instanceof Error ? err : new Error(String(err)));
                }
            };
        });
    }

    consumeInterceptedOutput(chunkText) {
        if (!this.outputInterceptor) {
            return false;
        }
        const interceptor = this.outputInterceptor;
        interceptor.buffer += chunkText;

        while (true) {
            const markerIndex = interceptor.buffer.indexOf(interceptor.marker);
            if (markerIndex === -1) {
                break;
            }

            const captured = interceptor.buffer.slice(0, markerIndex);
            const hasLineBreak = captured.includes('\n') || captured.includes('\r');

            if (!hasLineBreak) {
                // 命令回显触发了标记，丢弃后继续等待真实输出
                interceptor.buffer = interceptor.buffer.slice(markerIndex + interceptor.marker.length);
                continue;
            }

            const rest = interceptor.buffer.slice(markerIndex + interceptor.marker.length);
            this.outputInterceptor = null;
            if (typeof interceptor.resolve === 'function') {
                interceptor.resolve(captured);
            }
            if (rest) {
                this.forwardConsoleOutput(rest);
            }
            return true;
        }

        return true;
    }

    forwardConsoleOutput(text) {
        if (!text || this.commandMode) {
            return;
        }
        process.stdout.write(text);
    }

    selectLatestBuzzLog(listingOutput) {
        const sanitizedOutput = (listingOutput || '').replace(ANSI_COLOR_REGEX, '');
        const pattern = new RegExp(`${DEFAULT_LOG_PREFIX}\\.(\\d{4}-\\d{2}-\\d{2})\\.(\\d+)\\.log`, 'g');
        const candidates = [];
        let match;
        while ((match = pattern.exec(sanitizedOutput)) !== null) {
            candidates.push({
                file: match[0],
                date: match[1],
                index: parseInt(match[2], 10) || 0
            });
        }
        if (!candidates.length) {
            return null;
        }

        const today = DateUtil.today();
        const todays = candidates.filter(item => item.date === today);
        const pool = todays.length ? todays : candidates;
        pool.sort((a, b) => {
            if (a.date !== b.date) {
                return a.date > b.date ? -1 : 1;
            }
            return b.index - a.index;
        });
        return pool[0];
    }

    /**
     * 恢复终端正常模式
     */
    restoreTerminal() {
        if (process.stdin.isTTY) {
            process.stdin.setRawMode(false);
        }
        process.stdin.pause();
    }

    /**
     * 工具函数 - 检查空对象
     */
    isEmptyObject(obj) {
        return Object.keys(obj).length === 0 && obj.constructor === Object;
    }

    /**
     * 工具函数 - 问答
     */
    askQuestion(query) {
        return new Promise(resolve => {
            this.rl.question(query, answer => {
                resolve(answer);
            });
        });
    }

    /**
     * 执行命令解析
     */
    async execute(args) {
        try {
            // 确保在出错时清理资源
            process.on('SIGINT', () => {
                if (this.commandMode) {
                    // 在命令模式下，SIGINT 只是退出命令模式
                    this.commandMode = false;
                    this.inputBuffer = '';
                    console.log(chalk.gray('\n退出命令模式\n'));
                    return;
                }

                this.logger.warn('收到中断信号，正在清理...');
                this.restoreTerminal();
                if (this.rl) {
                    this.rl.close();
                }
                process.exit(0);
            });

            await this.program.parseAsync(args, { from: 'user' });
        } catch (error) {
            const stackLines = (error.stack || '').split('\n');
            const locationInfo = stackLines[1] ? stackLines[1].trim() : 'unknown location';
            this.logger.error(`OC 命令执行错误: ${error.message} (${locationInfo})`);
            this.restoreTerminal();
            if (this.rl) {
                this.rl.close();
            }
            process.exit(1);
        }
    }
}

// 导出执行函数供路由器调用
export const execute = async (args) => {
    const handler = new OcCommandHandler();
    await handler.execute(args);
};
